/*
 * Created by: 
 * Created: Monday, April 23, 2007
 */

using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Xml;
using Edge.Common.DataUtils;
using Edge.Common.Utils;
using Edge.Common.Utils;

namespace Edge.Common.Mail.Impl
{
    public class SendMailServiceConfigurator
    {
        private const string HOST_TAG = "host";
        private const string PORT_TAG = "port";
        private const string USER_TAG = "login";
        private const string PASSWRD_TAG = "passwrd";
        private const string ENABLED_TAG = "enabled";
        private const string DEFAULT_FROM_TAG = "defaultFrom";
        private const string DEFAULT_NAME_TAG = "defaultFromName";
        private const string TRACE_TAG = "trace";
        private const string TRACE_TO_TAG = "traceTo";

        private readonly SendMailService sendMailService;


        public SendMailServiceConfigurator(SendMailService sendMailService)
        {
            this.sendMailService = sendMailService;
        }

        public void Configure()
        {
            MailConfigSection mailSection = (MailConfigSection)System.Configuration.ConfigurationManager.GetSection("mail");
            if (mailSection == null)
                throw new ApplicationException("mail section missed");

            if (mailSection.XmlElement == null)
                throw new ApplicationException("mail section missed");

            Configure(mailSection.XmlElement);

        }

        //        public void Configure(string xmlContents)
        //        {
        //            XmlDocument doc = new XmlDocument();
        //            XmlElement xmlElement = (XmlElement)doc.ReadNode( new XmlTextReader(new StringReader(xmlContents)));
        //            Configure(doc.DocumentElement);
        //        }

        public void Configure(XmlElement xmlElement)
        {
            if (xmlElement == null)
                throw new ArgumentException("xmlElement");

            bool enabled = GetElementValue<bool>(xmlElement, ENABLED_TAG, true);

            if (!enabled)
            {
                sendMailService.Enabled = enabled;
                return;
            }

            string hostString = GetNotEmptyElementText(xmlElement, HOST_TAG);

            sendMailService.Host = hostString;

            int portString = Convert.ToInt32(GetNotEmptyElementText(xmlElement, PORT_TAG));

            sendMailService.Port = portString;

            string loginString = GetNotEmptyElementText(xmlElement, USER_TAG);

            sendMailService.Login = loginString;

            string passwrdString = GetNotEmptyElementText(xmlElement, PASSWRD_TAG);

            sendMailService.Passwrd = passwrdString;

            string defaultFrom = GetElementValue<string>(xmlElement, DEFAULT_FROM_TAG, null);
            string defaultFromName = GetElementValue<string>(xmlElement, DEFAULT_NAME_TAG, null);
            if (!StringUtils.IsBlankOrNull(defaultFrom))
            {
                sendMailService.PreSend += (new DefaultFromInterceptor(defaultFrom)).Intercept;
                sendMailService.DefaultFromField = defaultFrom;
                //sendMailService.DefaultFromName = defaultFromName;
            }

            if (GetElementValue<bool>(xmlElement, TRACE_TAG, false))
            {
                string traceTo = GetElementValue<string>(xmlElement, TRACE_TO_TAG, null);
                if (StringUtils.IsBlankOrNull(traceTo))
                {
                    throw new InvalidOperationException("Invalid value of element traceTo. Element value must be not empty if 'trace' element contains true");
                }
                sendMailService.PreSend += (new TraceInterceptor(traceTo)).Intercept;

            }

            sendMailService.Init();

        }

        private static string GetNotEmptyElementText(XmlElement xmlElement, string tagName)
        {
            XmlNodeList list = xmlElement.GetElementsByTagName(tagName);
            if (list.Count != 1)
                throw new InvalidOperationException("config section does not contains element " + tagName);

            XmlElement el = (XmlElement)list[0];
            if (StringUtils.IsBlankOrNull(el.InnerText))
                throw new InvalidOperationException("config element " + tagName + " is empty");
            return el.InnerText;
        }

        private static T GetElementValue<T>(XmlElement xmlElement, string tagName, T emptyValue)
        {
            XmlNodeList list = xmlElement.GetElementsByTagName(tagName);
            if (list.Count == 0)
                return emptyValue;

            if (list.Count > 1)
                throw new InvalidOperationException("more then one elements " + tagName);

            XmlElement el = (XmlElement)list[0];
            string text = el.InnerText;
            if (StringUtils.IsBlankOrNull(text))
                return emptyValue;

            //            TypeConverter converter = new TypeConverter();
            try
            {
                //                return (T)converter.ConvertTo(text, typeof (T));
                return (T)Convert.ChangeType(text, typeof(T));
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Invalid value of element " + tagName + " " + text);
            }
        }

    }
}